package com.kwan.xframe.common.service;

import android.app.Service;
import android.content.Intent;
import android.os.Binder;
import android.os.IBinder;
import android.support.annotation.Nullable;
import android.util.Log;

import com.kwan.xframe.mvp.presenter.IBaseView;
import com.kwan.xframe.util.ByteArrayUtil;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.net.Socket;
import java.util.HashMap;
import java.util.Map;

import okio.BufferedSink;
import okio.BufferedSource;
import okio.Okio;

public class JRemoteSocketService extends Service {

	private Socket mSocket;
	private static final int PORT = 12000; //12001;
	//private static final String IP = "t.ji-cloud.cn";
	private static final String IP = "192.168.2.10";//26 28
	//private static final String IP = "192.168.0.26";
	private LocalBinder binder = new LocalBinder();

	private final static int ReConnectTime = 2;
	private int mReConnectCount;
	private boolean isReConnect;

	public class LocalBinder extends Binder {
		public JRemoteSocketService getService() {
			return JRemoteSocketService.this;
		}
	}

	@Nullable
	@Override
	public IBinder onBind(Intent intent) {
		return binder;
	}

	@Override
	public void onCreate() {
		super.onCreate();
		connect();
	}

	private void connect() {

		new Thread() {
			@Override
			public void run() {
				super.run();
				try {

					if (mSocket != null && mSocket.isConnected()) {
						Log.e("JRemoteSocketService", "Socket is connect now 2 close");
						mSocket.close();
						mSocket = null;
					}

					if (mSink != null) {
						mSink.close();
						mSink = null;
					}

					if (mSource != null) {
						mSource.close();
						mSource = null;
					}

					isStopRead = false;
					mSocket = new Socket();
					Log.e("JRemoteSocketService", "开始连接");
					mSocket.connect(new InetSocketAddress(IP, PORT));
					Log.e("JRemoteSocketService", "JRemoteSocketService isConnected OK?" + mSocket.isConnected());
					mReConnectCount = 0;
					if (mServerListener != null) mServerListener.onConnected(isReConnect);
					isReConnect = false;
					receive();
				} catch (Exception e) {
					Log.e("JRemoteSocketService", "连接错误----准备重连");
					reconnect();
					e.printStackTrace();
				}
			}
		}.start();
	}


	public static final Object lock = new Object();

	private void reconnect() {

		synchronized (lock) {
			Log.e("JRemoteSocketService", "第" + mReConnectCount + "次重连");
			if (mReConnectCount == ReConnectTime) {
				mReConnectCount = 0;
				Log.e("JRemoteSocketService", "重连结束...");
				if (mServerListener != null) mServerListener.onConnectError(new Exception("连接失败"));
				return;
			}


			try {
				isStopRead = true;
				Thread.sleep(2000);
				Log.e("kwan", "isClosed ? " + mSocket.isClosed() + " isConnected ? " + mSocket.isConnected());

				if (mSocket != null && !mSocket.isClosed() && mSocket.isConnected()) {
					Log.e("JRemoteSocketService", "重连判断 已连接 计数重置...");
					if (mServerListener != null) mServerListener.onConnected(true);
					mReConnectCount = 0;
				} else {
					Log.e("JRemoteSocketService", "开始重连...");
					mReConnectCount++;
					isReConnect = true;
					connect();
				}

			} catch (Exception e) {
				e.printStackTrace();
			}
		}
	}


	BufferedSink mSink;

	public void send(final byte[] data) {

		new Thread() {
			@Override
			public void run() {
				super.run();

				try {

					if (mSocket != null && !mSocket.isClosed()) {
						Log.e("JRemoteSocketService", "send");
						mSink = Okio.buffer(Okio.sink(mSocket));
						mSink.write(data);
						mSink.flush();
					} else {
						Log.e("JRemoteSocketService", " send error mSocket null");
//						if (mServerListener != null) mServerListener.onError(new Exception("网络错误"));
						reconnect();
					}

				} catch (IOException e) {

					try {

						if (mSink != null) {
							mSink.close();
							mSink = null;
						}
					} catch (IOException e1) {
						e1.printStackTrace();
					}

					Log.e("JRemoteSocketService", "发送数据错误 --- 准备重连：" + e.getMessage());
					reconnect();

				}
			}
		}.start();


	}

	BufferedSource mSource;
	boolean isStopRead = false;

	private void receive() {

		new Thread() {
			@Override
			public void run() {
				super.run();

				try {

					mSource = Okio.buffer(Okio.source(mSocket));

					while (!isStopRead) {

						Thread.sleep(100);
						byte[] buffHead = new byte[2];
						byte data[] = new byte[]{};

						if (mSocket.isClosed()) {
							reconnect();
							return;
						}

						for (int i = 0; i < 2; i++) {
							if (mSource.read(buffHead) == 0) {
								Log.e("JRemoteSocketService", "接收包头数据错误 -- 准备重连");
								reconnect();
								return;
							}
							data = ByteArrayUtil.concatAll(data, buffHead);
						}

						//数据长度
						short sID = ByteArrayUtil.getShort(data, 0);
						short sLen = ByteArrayUtil.getShort(data, 2);

						if (sID == 0 && sLen == 0) {
							Log.i("JRemoteSocketService", Thread.currentThread().getId() + " 收到0 0 准备重连");
							reconnect();
							return;
						}

						Log.i("JRemoteSocketService", Thread.currentThread().getId() + " 接收数据包头 -- 实际数据长度：" + sLen + " 包头ID：" + sID);

						if (sID == 601) {// 心跳包
							send(data);
						} else {
							//根据数据长度 缓冲
							byte[] buffData = new byte[sLen];
							//byte[] data2 = new byte[sLen];

							int readBytes = 0;
							int tmp_readBytes;
							while (readBytes < sLen) {
								tmp_readBytes = mSource.read(buffData, readBytes, sLen - readBytes);

								if (tmp_readBytes >= 0) {
									readBytes += tmp_readBytes;
								} else {
									Log.e("JRemoteSocketService", "接收实际数据失败!");
									break;
								}
							}

							data = ByteArrayUtil.concatAll(data, buffData);

							if (readBytes == sLen) {
								//Log.e("kwan", "接收剩余数据 -- 数据长度：" + buffData);
								if (sID != 0) {

									Log.e("JRemoteSocketService", "mListeners size:" + mListeners.size());

									for (Map.Entry<IBaseView, HashMap<Short, ReceiveListener>> entry : mListeners.entrySet()) {
										Log.e("JRemoteSocketService", entry.getKey().toString());
										HashMap<Short, ReceiveListener> map = entry.getValue();
										if (map.get(sID) != null) {
											Log.e("JRemoteSocketService", "to notify:" + sID);
											map.get(sID).notifyData(data);
										}
									}
									//mListener.notifyData(data);
								}
							} else {
								//bytes = -1;
							}
						}
					}

				} catch (Exception e) {

					e.printStackTrace();

					try {

						if (mSource != null) {
							mSource.close();
							mSource = null;
						}

					} catch (IOException e1) {
						e1.printStackTrace();
					}

					reconnect();

				}
			}
		}.start();
	}


	ServerListener mServerListener;

	public interface ServerListener {

		void onConnected(boolean isReConnect);

		void onConnectError(Exception e);

		void onError(Exception e);

	}

	public void setConnectListener(ServerListener listener) {
		mServerListener = listener;
	}


	private HashMap<IBaseView, HashMap<Short, ReceiveListener>> mListeners = new HashMap<>();

	public interface ReceiveListener {
		void notifyData(byte[] data);
	}

	public void addReceiveListener(IBaseView iBaseView, HashMap<Short, ReceiveListener> map) {
		mListeners.put(iBaseView, map);
	}

	public void removeReceiveListener(IBaseView iBaseView) {
		mListeners.remove(iBaseView);
	}

	@Override
	public int onStartCommand(Intent intent, int flags, int startId) {
		return super.onStartCommand(intent, flags, startId);
	}

	@Override
	public void onDestroy() {
		super.onDestroy();
	}

	public Boolean isServerClose(Socket socket) {
		try {
			//发送1个字节的紧急数据，默认情况下，服务器端没有开启紧急数据处理，不影响正常通信
			socket.sendUrgentData(0xFF);
			return false;
		} catch (Exception se) {
			return true;
		}
	}
}
